package com.uniflow.util;

import com.uniflow.entity.AuditLogs;
import com.uniflow.entity.User;
import com.uniflow.service.AuditLogService;
import com.uniflow.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;

/**
 * 审计日志工具类
 * 统一处理审计日志记录，避免各Service中重复代码
 * 
 * @author uniflow
 * @since 1.0.0
 */
@Component
public class AuditLogHelper {
    
    @Autowired
    private AuditLogService auditLogService;
    
    @Autowired
    private UserService userService;
    
    /**
     * 记录审计日志
     * 
     * @param operationType 操作类型
     * @param resourceType 资源类型
     * @param resourceId 资源ID
     * @param description 操作描述
     * @param result 操作结果
     * @param userId 操作用户ID
     */
    public void recordLog(String operationType, String resourceType, String resourceId, 
                         String description, String result, String userId) {
        recordLog(operationType, resourceType, resourceId, null, description, result, userId, null, null);
    }
    
    /**
     * 记录审计日志（完整版）
     * 
     * @param operationType 操作类型
     * @param resourceType 资源类型
     * @param resourceId 资源ID
     * @param resourceName 资源名称
     * @param description 操作描述
     * @param result 操作结果
     * @param userId 操作用户ID
     * @param oldData 变更前数据
     * @param newData 变更后数据
     */
    public void recordLog(String operationType, String resourceType, String resourceId, String resourceName,
                         String description, String result, String userId, String oldData, String newData) {
        try {
            AuditLogs auditLog = new AuditLogs();
            auditLog.setUserId(userId);
            auditLog.setOperationType(operationType);
            auditLog.setResourceType(resourceType);
            auditLog.setResourceId(resourceId);
            auditLog.setResourceName(resourceName);
            auditLog.setOperationDesc(description);
            auditLog.setOperationResult(result);
            auditLog.setOperationTime(LocalDateTime.now());
            auditLog.setOldData(oldData);
            auditLog.setNewData(newData);
            
            // 获取用户信息
            if (StringUtils.hasText(userId)) {
                try {
                    User user = userService.getUserById(userId);
                    if (user != null) {
                        auditLog.setUsername(user.getUsername());
                    }
                } catch (Exception e) {
                    // 获取用户信息失败不影响审计日志记录
                }
            }
            
            // 获取请求信息
            try {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                if (attributes != null) {
                    HttpServletRequest request = attributes.getRequest();
                    auditLog.setRequestIp(getClientIpAddress(request));
                    auditLog.setUserAgent(request.getHeader("User-Agent"));
                    auditLog.setRequestUrl(request.getRequestURL().toString());
                    auditLog.setRequestMethod(request.getMethod());
                }
            } catch (Exception e) {
                // 获取请求信息失败不影响审计日志记录
            }
            
            auditLogService.createAuditLog(auditLog);
        } catch (Exception e) {
            // 审计日志记录失败不应影响主业务流程
            System.err.println("记录审计日志失败: " + e.getMessage());
        }
    }
    
    /**
     * 记录登录日志
     */
    public void recordLogin(String userId, String username, boolean success, String errorMessage) {
        String result = success ? "SUCCESS" : "FAILURE";
        String description = success ? "用户登录成功: " + username : "用户登录失败: " + username;
        if (!success && StringUtils.hasText(errorMessage)) {
            description += ", 原因: " + errorMessage;
        }
        recordLog("LOGIN", "USER", userId, username, description, result, userId, null, null);
    }
    
    /**
     * 记录登出日志
     */
    public void recordLogout(String userId, String username) {
        recordLog("LOGOUT", "USER", userId, username, "用户登出: " + username, "SUCCESS", userId, null, null);
    }
    
    /**
     * 记录创建操作
     */
    public void recordCreate(String resourceType, String resourceId, String resourceName, 
                            String userId, String newData) {
        recordLog("CREATE", resourceType, resourceId, resourceName, 
                 "创建" + resourceType + ": " + resourceName, "SUCCESS", userId, null, newData);
    }
    
    /**
     * 记录更新操作
     */
    public void recordUpdate(String resourceType, String resourceId, String resourceName, 
                            String userId, String oldData, String newData) {
        recordLog("UPDATE", resourceType, resourceId, resourceName, 
                 "更新" + resourceType + ": " + resourceName, "SUCCESS", userId, oldData, newData);
    }
    
    /**
     * 记录删除操作
     */
    public void recordDelete(String resourceType, String resourceId, String resourceName, 
                            String userId, String oldData) {
        recordLog("DELETE", resourceType, resourceId, resourceName, 
                 "删除" + resourceType + ": " + resourceName, "SUCCESS", userId, oldData, null);
    }
    
    /**
     * 记录流程操作
     */
    public void recordWorkflowOperation(String operationType, String processInstanceId, 
                                       String processDefinitionKey, String userId, String description) {
        recordLog(operationType, "PROCESS_INSTANCE", processInstanceId, processDefinitionKey, 
                 description, "SUCCESS", userId, null, null);
    }
    
    /**
     * 记录API操作
     */
    public void recordApiOperation(String operationType, String resourceType, String resourceId, 
                                  String userId, String description, boolean success) {
        String result = success ? "SUCCESS" : "FAILURE";
        recordLog(operationType, resourceType, resourceId, null, description, result, userId, null, null);
    }
    
    /**
     * 获取客户端真实IP地址
     */
    private String getClientIpAddress(HttpServletRequest request) {
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (StringUtils.hasText(xForwardedFor) && !"unknown".equalsIgnoreCase(xForwardedFor)) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeader("X-Real-IP");
        if (StringUtils.hasText(xRealIp) && !"unknown".equalsIgnoreCase(xRealIp)) {
            return xRealIp;
        }
        
        String proxyClientIp = request.getHeader("Proxy-Client-IP");
        if (StringUtils.hasText(proxyClientIp) && !"unknown".equalsIgnoreCase(proxyClientIp)) {
            return proxyClientIp;
        }
        
        String wlProxyClientIp = request.getHeader("WL-Proxy-Client-IP");
        if (StringUtils.hasText(wlProxyClientIp) && !"unknown".equalsIgnoreCase(wlProxyClientIp)) {
            return wlProxyClientIp;
        }
        
        return request.getRemoteAddr();
    }
    
    /**
     * 操作类型常量
     */
    public static class OperationType {
        public static final String CREATE = "CREATE";
        public static final String UPDATE = "UPDATE";
        public static final String DELETE = "DELETE";
        public static final String LOGIN = "LOGIN";
        public static final String LOGOUT = "LOGOUT";
        public static final String EXPORT = "EXPORT";
        public static final String IMPORT = "IMPORT";
        public static final String APPROVE = "APPROVE";
        public static final String REJECT = "REJECT";
        public static final String DEPLOY = "DEPLOY";
        public static final String START = "START";
        public static final String COMPLETE = "COMPLETE";
        public static final String ASSIGN = "ASSIGN";
        public static final String TRANSFER = "TRANSFER";
        public static final String PROCESS_START = "PROCESS_START";
        public static final String PROCESS_END = "PROCESS_END";
        public static final String TASK_CREATE = "TASK_CREATE";
        public static final String TASK_COMPLETE = "TASK_COMPLETE";
        public static final String CHANGE_PASSWORD = "CHANGE_PASSWORD";
        public static final String RESET_PASSWORD = "RESET_PASSWORD";
        public static final String REGISTER = "REGISTER";
    }
    
    /**
     * 资源类型常量
     */
    public static class ResourceType {
        public static final String USER = "USER";
        public static final String ROLE = "ROLE";
        public static final String PERMISSION = "PERMISSION";
        public static final String ORGANIZATION = "ORGANIZATION";
        public static final String PROCESS_DEFINITION = "PROCESS_DEFINITION";
        public static final String PROCESS_INSTANCE = "PROCESS_INSTANCE";
        public static final String TASK = "TASK";
        public static final String TASK_CENTER = "TASK_CENTER";
        public static final String FORM = "FORM";
        public static final String FORM_DATA = "FORM_DATA";
        public static final String API_APPLICATION = "API_APPLICATION";
        public static final String API_KEY = "API_KEY";
        public static final String SYSTEM_CONFIG = "SYSTEM_CONFIG";
        public static final String SYNC_SOURCE = "SYNC_SOURCE";
        public static final String SYNC_TASK = "SYNC_TASK";
        public static final String THIRD_PARTY_INTEGRATION = "THIRD_PARTY_INTEGRATION";
    }
}